package com.climber.android.commonsdk.api.entity

import com.google.gson.annotations.SerializedName
import java.io.Serializable
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.ArrayList
import java.util.HashMap

/**
 * Created by Mikes at 2019-11-04 08:32
 */

const val HTTP_CODE_SUCCESSFUL = 20000
const val URL_NEED_TOKEN = 30003            // 必须登录才可以使用该功能
const val TOKEN_EXPIRED = 40001

open class APIResponse : Serializable {

    @SerializedName("code")
    var errorCode: Int? = null

    @SerializedName("msg")
    var errorMsg: String? = null

    var extra: Map<String, String>? = null
        get() {
            if (field == null) {
                field = HashMap()
            }
            return field
        }

    /**
     * @return errorCode is 0 means successful. code is 200 means successful.
     */
    fun isSuccessful(): Boolean {
        return if (errorCode != null) {
            errorCode == HTTP_CODE_SUCCESSFUL
        } else {
            false
        }
    }

    fun getServerErrorCode(): Int {
        return errorCode ?: -1
    }

    fun getServerErrorMsg(): String {
        return errorMsg ?: ""
    }
}

class APIResponseData<T> : APIResponse() {
    var data: T? = null
}

class APIResponseListData<T> : APIResponse() {
    var data: ArrayList<T>? = null

    val isEmptyData: Boolean
        get() = data?.isEmpty() ?: true
}

open class APIPageableResponseListData<T> : APIResponse() {
    var data: PageableListData<T>? = null

    val pageableData : ArrayList<T>?
        get() = data?.data

    val hasMoreData: Boolean
        get() = (data?.current_page ?: 1) <= (data?.last_page ?: 1)

    val isLastPage: Boolean
        get() = (data?.current_page ?: 1) == (data?.last_page ?: 1)

    val isEmptyData: Boolean
        get() = pageableData?.isEmpty() ?: true
}

data class PageableListData<T>(
    var total : Int? = null,
    var per_page : String? = null,
    var current_page : Int? = null,
    var last_page : Int? = null,

    var data: ArrayList<T>? = null
)

// List<T> 解决Gson解析时发生的泛型擦除问题
class ListParameterizedType(val type : Type) : ParameterizedType {
    override fun getRawType(): Type = ArrayList::class.java

    override fun getOwnerType(): Type?= null

    override fun getActualTypeArguments(): Array<Type> = arrayOf(type)
}

// 待解决Gson解析时，编译器泛型擦除导致返回的数据类型是LinkedTreeMap
class APIParameterizedType<R>(val cls : Class<R>) : ParameterizedType {
    override fun getRawType(): Type = cls

    override fun getOwnerType(): Type?= null

    override fun getActualTypeArguments(): Array<Type> = arrayOf(cls)
}
